<template>
  <y-dialog v-bind="dialogOptions" :loading="loading" :title="title" ref="dialogRef" @ok="$refs.formRef.submit()">
    <y-form ref="formRef" :options="formOptions" @submit="submit">
      <template #[slot]="{ data }" v-for="slot in formSlotNames">
        <!-- 传入 slotNames -->
        <slot :name="slot" v-bind="{ data }">
        </slot>
      </template>
    </y-form>
  </y-dialog>
</template>

<script>
import { cloneDeep } from '@/utils';
import request from '@/utils/request'

export default {
  props: {
    // 表单数据唯一键值
    keyId: {
      type: String,
      default: 'id'
    },
    // 接口
    link: Object,
    // 弹窗名称
    title: {
      type: String,
      default: '表单弹窗'
    },
    // 表单配置
    formOptions: Object
  },
  data() {
    return {
      dialogOptions: {},
      // 弹窗配置
      loading: false,
      formSlotNames: [],
    }
  },
  watch: {
    formOptions: {
      deep: true,
      immediate: true,
      handler(newVal) {
        if (this.formOptions) {
          this.formSlotNames = this.setFormSlot(this.formOptions);
        }
      }
    }
  },
  methods: {
    setFormSlot(formOptions) {
      // 初始化用于存储表单插槽名称的数组
      const formSlotNames = [];

      /**
         * 辅助函数：递归处理 items 和 children 数组
         *
         * 该函数负责递归地检查传入的项目数组，寻找并收集默认插槽名称
         * 它通过检查每个项目是否包含 slots 属性以及该属性是否定义了默认插槽来收集插槽名称
         * 如果项目包含子项目（children），则递归调用自身以处理这些子项目
         *
         * @param {Array} items - 项目数组，可以是父项目数组或子项目数组
         */
      function processItems(items) {
        // 如果传入的不是数组，则直接返回，不进行处理
        if (!Array.isArray(items)) return;

        // 遍历项目数组，处理每个项目
        for (const item of items) {
          // 如果项目定义了插槽且包含默认插槽，则将其添加到结果数组中
          if (item.slots && item.slots.default) {
            formSlotNames.push(item.slots.default);
          }

          // 如果项目包含子项目，则递归调用以处理这些子项目
          if (item.children && Array.isArray(item.children)) {
            processItems(item.children);
          }
        }
      }

      // 尝试处理表单配置，如果配置有效且包含 items 数组，则开始处理
      try {
        if (formOptions && Array.isArray(formOptions.items)) {
          processItems(formOptions.items);
        }
      } catch (error) {
        // 如果在处理过程中发生错误，则输出错误信息
        console.error('Error processing form options:', error);
      }

      // 返回包含收集到的表单插槽名称的对象
      return {
        formSlotNames
      };
    },
    // 打开弹窗
    open(formData) {
      this.$refs.dialogRef.open();
      // 设置数据
      this.$nextTick(() => {
        // 请求接口
        this.$refs.formRef.setData(formData)
      })
    },
    // 关闭弹窗
    close() {
      this.$refs.dialogRef.close();
    },
    // 点击确认提交
    async submit(data) {
      this.loading = true

      try {
        if (this.link) {
          if (data[this.keyId]) {
            await this.edit(data)
          } else {
            await this.add(data)
          }
          this.$message.success('提交成功')
          this.loading = false
          this.close()
          this.$emit('confirm')
        } else {
          const form = cloneDeep(this.$refs.formRef.formOptions.data)
          const res = await this.$listeners.confirm(form)
          if (res) {
            this.loading = false
            this.close()
          }
        }
      } catch (error) {
        this.loading = false
      }

    },
    // 编辑提交
    edit(data) {
      return request({
        url: this.link.edit,
        method: 'post',
        data
      })
    },
    // 新增提交
    add(data) {
      return request({
        url: this.link.add,
        method: 'post',
        data
      })
    },

  }
}
</script>

<style lang="scss" scoped></style>
